#ifndef __LOOPTHREAD_HPP__
#define __LOOPTHREAD_HPP__

#include <thread>
#include <mutex>
#include <condition_variable>

class LoopThread
{
private:
    /* 线程入口函数——内部实例化EventLoop对象，唤醒_cond上可能阻塞的线程，启动EventLoop模块 */
    void ThreadEntry()
    {
        EventLoop loop; // 这里不使用new，是为了让loop对象的生命周期随当前局部作用域
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _loop = &loop;

            _cond.notify_all(); // 唤醒_cond上可能阻塞的线程
        }
        loop.Start(); // 因为EventLoop模块是一直运行的，所以让loop对象的生命周期随当前局部作用域
    }

public:
    /* 构造函数内：创建线程，设置线程入口函数 */
    LoopThread() : _loop(nullptr), _thread(std::thread(&LoopThread::ThreadEntry, this))
    {
    }
    /* 获取Loop线程对应的EventLoop对象指针 */
    EventLoop *GetEventLoop()
    {
        EventLoop *loop = nullptr;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _cond.wait(lock, [&]()
                       { return _loop != nullptr; }); // _loop为空就一直阻塞，等待被唤醒

            loop = _loop;
        }
        return loop;
    }

private:
    EventLoop *_loop;    // EventLoop对象的指针，对象需要在_thread线程内实例化
    std::thread _thread; // EventLoop对应的线程

    /* 互斥锁和条件变量——保证获取_loop操作是互斥且同步的，避免在实例化之前就获取_loop */
    std::mutex _mutex;             // 互斥锁
    std::condition_variable _cond; // 条件变量
};

class LoopThreadPool
{
public:
    LoopThreadPool(EventLoop *base_loop) : _base_loop(base_loop), _thread_count(0), _next_loop_index(0)
    {
    }
    /* 设置从属线程数量 */
    void SetThreadCount(int count)
    {
        _thread_count = count;
    }
    /* 创建所有从属线程 */
    void Create()
    {
        if (_thread_count > 0)
        {
            _threads.resize(_thread_count);
            _loops.resize(_thread_count);
            for (int i = 0; i < _thread_count; ++i)
            {
                _threads[i] = new LoopThread();
                _loops[i] = _threads[i]->GetEventLoop();
            }
        }
    }
    /* 获取下一个要分配的线程 */
    EventLoop *NextLoop()
    {
        if (_thread_count == 0)
            return _base_loop;
        
        EventLoop *&loop = _loops[_next_loop_index];
        ++_next_loop_index;
        _next_loop_index %= _thread_count;
        return loop;
    }

private:
    EventLoop *_base_loop;              // 主EventLoop，运行在主线程中。若从属线程数量为0，则所有的操作都在主线程中进行
    int _thread_count;                  // 从属线程的数量
    int _next_loop_index;               // 要取的EventLoop在_loops中的索引
    std::vector<LoopThread *> _threads; // 保存loop线程池中的线程
    std::vector<EventLoop *> _loops;    // 保存所有的EventLoop。若从属线程数量大于0，则将操作分配给_loops中的某个EventLoop
};

#endif